package com.ruoyi.outpatient.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.constant.PersonConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.outpatient.core.LoginPatient;
import com.ruoyi.outpatient.core.ScrollData;
import com.ruoyi.outpatient.core.SecurityUtils;
import com.ruoyi.outpatient.domain.Blog;
import com.ruoyi.outpatient.domain.Follow;
import com.ruoyi.outpatient.domain.Person;
import com.ruoyi.outpatient.mapper.IBlogMapper;
import com.ruoyi.outpatient.mapper.IFollowMapper;
import com.ruoyi.outpatient.mapper.IPersonLoginMapper;
import com.ruoyi.outpatient.service.IFollowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 伟峰
 * @date 2022/5/4
 * @description:
 */
@Service
public class FollowServiceImpl implements IFollowService {

    @Autowired
    private IFollowMapper followMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IPersonLoginMapper personMapper;

    @Autowired
    private SecurityUtils securityUtils;


    @Autowired
    private IBlogMapper blogMapper;


    /**
     * 关注我的粉丝列表
     * @return
     */
    @Override
    public AjaxResult fansList() {


        Long loginPersonId = securityUtils.getLoginPersonId();

//        1.先查询redis是否有我的粉丝
//        redisCache.getCacheZSetForSco(PersonConstants.FOLLOW_FANS,)
//        2.有返回

//        3.没有则查询数据库
//        3.1.查询获取我的id查询我的粉丝列表
        List<Person> fans=personMapper.selectFansList(loginPersonId);

//        3.2将数据库的集合一次性存入redis中
//        Set<ZSetOperations.TypedTuple> typedTupleSet = new HashSet<ZSetOperations.TypedTuple>();
//        for (Person f:fans){
//            Long now= f.getCreateTime().getTime();
//            double followTime = now.doubleValue();
//            ZSetOperations.TypedTuple typedTuple1 =new DefaultTypedTuple(f, followTime);
//            typedTupleSet.add(typedTuple1);
//        }
//        redisCache.setCacheZSet(PersonConstants.FOLLOW_FANS+person.getPersonId(),typedTupleSet);
        return AjaxResult.success().put("fans",fans);
    }

    /**
     * 我关注的博主列表
     * @return
     */
    @Override
    public AjaxResult blogerList() {

        Long loginPersonId = securityUtils.getLoginPersonId();
        List<Person> bloger=personMapper.selectBlogerList(loginPersonId);

        return AjaxResult.success().put("bloger",bloger);
    }

    /**
     * 共同关注列表
     * @param id 目标用户
     * @return
     */
    @Override
    public AjaxResult commonList(Long id) {

//        1.获取自己ID
        Long loginPersonId = securityUtils.getLoginPersonId();

        String myKey="follow:list:" + loginPersonId;
        String targetKey="follow:list:" + id;
//        2.将自己id和目标用户id 求交集
        Set<String> set = redisCache.intersectSet(myKey, targetKey);
        if (set==null || StringUtils.isEmpty(set)){
            return AjaxResult.success("无共同关注").put("no",null);
        }
//        3.将集合string转为long
        List<Long> collect = set.stream().map(Long::valueOf).collect(Collectors.toList());

//        List<String> list2 = new ArrayList<String>();
//        List<Long> list3 = new ArrayList<Long>();
//        list2.addAll(set);
//        for(String elem : list2){
//            list3.add(Long.valueOf(elem));
//            System.out.println(elem);
//        }

//        4.查询共同关注的用户
        List<Person> personList =personMapper.selectPersonList(collect);

        return AjaxResult.success("共同关注").put("yes",personList);
    }


    /**
     * 消息推送到粉丝
     * @param lastTime 本次要查询开始时间,也是上次结束时间
     * @param offset 查询偏移量 如果默认0即第一次查询
     * @return
     */
    @Override
    public AjaxResult messageList(Long lastTime, Long offset) {
        Long loginPersonId = securityUtils.getLoginPersonId();

        Set<ZSetOperations.TypedTuple> zSetRangeByScore = redisCache  //0从上往下所有一直为0
                .getZSetRangeByScore("follow:feed:" + loginPersonId, 0, lastTime, offset, 10L);

        List<Long> ids=new ArrayList<>(zSetRangeByScore.size());
        List<Long> descTime=new ArrayList<>(zSetRangeByScore.size());
        long mintime=0;
        long off=1;
        for (ZSetOperations.TypedTuple f:zSetRangeByScore){
//            将所有粉丝id存到list
            ids.add(Long.valueOf(f.getValue().toString())); //id
            long time=f.getScore().longValue(); //时间


            if (time==mintime){
                off++;
            }else {
                mintime=time;
                off=1;
            }
        }

//        通过id查询blog返回
        List<Blog> blogs = blogMapper.selectBlogListByTime(ids);


        ScrollData scrollData=new ScrollData();
        scrollData.setList(blogs);
        scrollData.setMinTime(mintime);
        scrollData.setOffset(off);
        return AjaxResult.success().put("消息推送",scrollData);
    }


    /**
     * 进行关注或取消关注
     * @param followPersonId 要关注的用户id
     * @param bool true为关注，false为取关
     * @return
     */
    @Override
    public AjaxResult updateFollowByPersonId(Long followPersonId, Boolean bool) {


//        1.获取自己的用户id
        Long loginPersonId = securityUtils.getLoginPersonId();


//        判断关注还是取关
//                如果bool为true说明已经关注,现在要取关 false为没关注现在要关注(bool是已经查询过了)
        if (bool){
            Follow follow=new Follow();
            follow.setPersonId(loginPersonId);
            follow.setFollowPersonId(followPersonId);
            Boolean isSuccess=followMapper.insert(follow);

            if (isSuccess){  //存到set集合中
                Long aLong = redisCache.setCacheSets("follow:list:" + loginPersonId, followPersonId.toString());
            }else {
                return AjaxResult.error(); //进行关注,出现异常
            }
//            统计30天内新增的粉丝
            if (redisCache.exists("statistics:myFansSum:"+loginPersonId)){
                redisCache.setCacheIncrement("statistics:myFansSum:"+loginPersonId); //加1
            }else {
                redisCache.setCacheObject("statistics:myFansSum:"+loginPersonId,1,30, TimeUnit.DAYS);
            }
            return AjaxResult.success("关注成功");
        }else {
            Follow follow=new Follow();
            follow.setPersonId(loginPersonId);
            follow.setFollowPersonId(followPersonId);
//            follow.setCreateTime(DateTime.now());
            Boolean isSuccess=followMapper.deleteFollow(follow);
            if (isSuccess){   //存到set集合中
                Long aLong = redisCache.setRemove("follow:list:" + loginPersonId, followPersonId.toString());
            }else {
                return AjaxResult.error(); //取消关注失败,异常
            }


            //            统计30天内新增的粉丝
            if (redisCache.exists("statistics:myFansSum:"+loginPersonId)){
                redisCache.setCacheDecrement(1); //减1
            }else {
                redisCache.setCacheObject("statistics:myFansSum:"+loginPersonId,0,30, TimeUnit.DAYS);
            }
            return AjaxResult.success("取关成功");
        }

    }



    /**
     * 查询用户是否关注
     * @param followPersonId 用户id
     * @return
     */
    @Override
    public AjaxResult isfollow(Long followPersonId) {

        Long loginPersonId = securityUtils.getLoginPersonId();
//        判断该用户是否被我关注了
//        select count(*) from follow where person_id= and followperson_id=
        Integer count= followMapper.selectIsFollow(loginPersonId,followPersonId);
        if (count>0){
            return AjaxResult.success().put("yesConcern",true);
        }else {
            return AjaxResult.success().put("noCncern",false);
        }

    }


}
